/*
 * @Author: 0x9DEFA478
 * @Date: 2021-08-30 19:51:49
 * @LastEditTime: 2021-09-09 18:33:02
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * QQ:2652450237
 * ============================================================================================================================================
 * 
 * 
 * 
 *                                                                                               ************      ****************************
 *                                                                                             ************      ****************************  
 *                                                                                           ************      ****************************    
 *                                                                                         ************      ****************************      
 *                                                                                       ************      ************                        
 *                                                                                     ************      ************                          
 *                                                                                   ************      ************                            
 *                                                                                 ************      ************                              
 *                                                                               ************      ************                                
 *                                                                             ************      ************                                  
 *                                                                           ************      ************                                    
 *                                                                         ************      ************                                      
 *                                                                       ************      ************                                        
 *                                                                     ************      ************                                          
 *                                                                   ************      ************                                            
 *                                                                 ************      ************                                              
 *                                                               ************      ************                                                
 *                                                             ************      ************                                                  
 *                                                           ************      ************                                                    
 *                                                         ************      ************                                                      
 *                                                       ************      ************                                                        
 *                                                     ************      ************                                                          
 *                                                   ************      ************                                                            
 *                                                 ************      ************                                                              
 *                                               ************      ************                                                                
 *                                             ************      ************                                                                  
 *                                           ************      ************                                                                    
 *                                         ************      ************                                                                      
 *                                       ************      ************                                                                        
 *                                     ************      ************                                                                          
 *                                   ************      ************                                                                            
 *                                 ************      ************                                                                              
 *                               ************      ************                                                                                
 *                             ************      ************                                                                                  
 *                           ************      ************                                                                                    
 *                         ************      ************                                                                                      
 *       ****************************      ************                                                                                        
 *     ****************************      ************                                                                                          
 *   ****************************      ************                                                                                            
 * ****************************      ************                                                                                              
 * 
 * 
 * 
 * ============================================================================================================================================
 * 
 */
#include "H_AudioResample.h"

static void H_AudioResample_WriteToOutput(H_AudioResample* ar,H_AudioResample_FloatType* Buffer,int Length);
static void H_AudioResample_VolumeConvert(H_AudioResample* ar,H_AudioResample_FloatType* Buffer,int Length);
static void H_AudioResample_CubicInterpolation(H_AudioResample* ar,H_AudioResample_FloatType* Buffer,int Length);

/**
 * @brief 获取可写入包数
 * @param ar H_AudioResample对象
 * @return 可写入包数
 */
int H_AudioResample_GetEmptyCount(H_AudioResample* ar){

  int I;
  int O;
  int EmptyCount;

  I=ar->Output.I;
  O=ar->Output.O;

  if(I<O){
    EmptyCount=O-I;
  }else{
    EmptyCount=ar->Output.OutputBufferBlockAllCount-I+O;
  }

  return EmptyCount-(ar->Output.OutputBufferBlockAllCount-ar->Output.OutputBufferBlockMaxCount);
  
}

/**
 * @brief 输出数据方法
 * @param ar H_AudioResample对象
 * @return 如果为NULL 表示目前无数据输出 否则为数据数据的指针
 */
H_AudioResample_IntegerType* H_AudioResample_Output(H_AudioResample* ar){
  H_AudioResample_IntegerType* r;
  int I;
  int O;

  if(ar->IsSuspend!=0){
    return NULL;
  }

  I=ar->Output.I;
  O=ar->Output.O;

  r=NULL;
  if(I!=O){

    r=&ar->Output.Buffer[O*ar->Output.SizeOfPerOutput];

    if(O==(ar->Output.OutputBufferBlockAllCount-1)){
      ar->Output.O=0;
    }else{
      ar->Output.O=O+1;
    }
  }

  return r;
}

/**
 * @brief 向ar中写入数据
 * @param ar H_AudioResample对象
 * @param Buffer 数据缓存
 * @param Length 数据长度 要求为2的倍数 单位:sizeof(H_AudioResample_IntegerType)字节
 * @return 0:成功 其他:as已挂起或缓存满
 */
int H_AudioResample_Input(H_AudioResample* ar,H_AudioResample_IntegerType* Buffer,int Length){

  int LastInputLength;
  H_AudioResample_FloatType* Buffer_Write;

  if(ar->IsSuspend!=0){
    return -1;
  }

  if((Length%2)!=0){
    return -2;
  }

  LastInputLength=ar->Input.LastInputLength;
  Buffer_Write=ar->Input.Buffer_WritePtr;

  while((Length>=8)&&(LastInputLength>=8)){
    Length-=8;
    LastInputLength-=8;
    
    Buffer_Write[0]=(H_AudioResample_FloatType)Buffer[0];
    Buffer_Write[1]=(H_AudioResample_FloatType)Buffer[1];
    Buffer_Write[2]=(H_AudioResample_FloatType)Buffer[2];
    Buffer_Write[3]=(H_AudioResample_FloatType)Buffer[3];
    Buffer_Write[4]=(H_AudioResample_FloatType)Buffer[4];
    Buffer_Write[5]=(H_AudioResample_FloatType)Buffer[5];
    Buffer_Write[6]=(H_AudioResample_FloatType)Buffer[6];
    Buffer_Write[7]=(H_AudioResample_FloatType)Buffer[7];

    Buffer=&Buffer[8];
    if(LastInputLength==0){
      Buffer_Write=ar->Input.Buffer;
      H_AudioResample_WriteToOutput(ar,Buffer_Write,ar->Input.SizeOfPerInput);
      LastInputLength=ar->Input.SizeOfPerInput;
    }else{
      Buffer_Write=&Buffer_Write[8];
    }
  }
  while(Length>0){
    Length--;
    LastInputLength--;

    Buffer_Write[0]=(H_AudioResample_FloatType)Buffer[0];
    
    Buffer=&Buffer[1];
    if(LastInputLength==0){
      Buffer_Write=ar->Input.Buffer;
      H_AudioResample_WriteToOutput(ar,Buffer_Write,ar->Input.SizeOfPerInput);
      LastInputLength=ar->Input.SizeOfPerInput;
    }else{
      Buffer_Write=&Buffer_Write[1];
    }
  }

  ar->Input.LastInputLength=LastInputLength;
  ar->Input.Buffer_WritePtr=Buffer_Write;

  return 0;
}

//音量转换 分支输出 重采样写入
static void H_AudioResample_WriteToOutput(H_AudioResample* ar,H_AudioResample_FloatType* Buffer,int Length){
  H_AudioResample_ExtProcess* Process;

  int EmptyCount;
  int OccupyCount;


  EmptyCount=H_AudioResample_GetEmptyCount(ar);

  if(EmptyCount==0){
    return;
  }

  OccupyCount=ar->Output.OutputBufferBlockMaxCount-EmptyCount;
  ar->Output.OccupyCount=OccupyCount;

  if(ar->ResampleCtrl.IsDefaultSpeed==0){
    if(OccupyCount<ar->ResampleCtrl.Threshold_SpeedUp){
      ar->ResampleCtrl.Status=vH_AudioResample_ResampleCtrl_Status_SpeedUp;
    }else if(OccupyCount>ar->ResampleCtrl.Threshold_SpeedDown){
      ar->ResampleCtrl.Status=vH_AudioResample_ResampleCtrl_Status_SpeedDown;
    }else{

      switch(ar->ResampleCtrl.Status){
        case vH_AudioResample_ResampleCtrl_Status_SpeedUp:
          if(OccupyCount>ar->ResampleCtrl.Threshold_SpeedUpStop){
            ar->ResampleCtrl.Status=vH_AudioResample_ResampleCtrl_Status_SpeedDefault;
          }
          break;
        case vH_AudioResample_ResampleCtrl_Status_SpeedDown:
          if(OccupyCount<ar->ResampleCtrl.Threshold_SpeedDownStop){
            ar->ResampleCtrl.Status=vH_AudioResample_ResampleCtrl_Status_SpeedDefault;
          }
          break;
        default:
          break;
      }
    }
  }else{
    ar->ResampleCtrl.Status=vH_AudioResample_ResampleCtrl_Status_SpeedDefault;
  }

  H_AudioResample_VolumeConvert(ar,Buffer,Length);//声道控制 音量控制

  Process=ar->Process;
  while(Process!=NULL){
    Process->Process(Process->v,Buffer,Length);
    Process=Process->Next;
  }

  H_AudioResample_CubicInterpolation(ar,Buffer,Length);//重采样转换 虽然不一定真的要重采样就是了

}

//输出浮点到原缓存
static void H_AudioResample_VolumeConvert(H_AudioResample* ar,H_AudioResample_FloatType* Buffer,int Length){
  H_AudioResample_FloatType Channel0;
  H_AudioResample_FloatType Channel1;
  H_AudioResample_FloatType Channel0_AmplitudeMultiple;
  H_AudioResample_FloatType Channel1_AmplitudeMultiple;

  Channel0_AmplitudeMultiple=ar->Volume.Channelx_AmplitudeMultiple[0];
  Channel1_AmplitudeMultiple=ar->Volume.Channelx_AmplitudeMultiple[1];

  Length/=2;//将长度转换位采样数量

  switch(ar->Volume.ChannelMode){
    case vH_AudioResample_Volume_ChannelMode_ChannelL:

      while(Length>=8){
        Length-=8;

        Channel0=Buffer[0];
        Buffer[0]=Channel0*Channel0_AmplitudeMultiple;
        Buffer[1]=Channel0*Channel1_AmplitudeMultiple;

        Channel0=Buffer[2];
        Buffer[2]=Channel0*Channel0_AmplitudeMultiple;
        Buffer[3]=Channel0*Channel1_AmplitudeMultiple;

        Channel0=Buffer[4];
        Buffer[4]=Channel0*Channel0_AmplitudeMultiple;
        Buffer[5]=Channel0*Channel1_AmplitudeMultiple;

        Channel0=Buffer[6];
        Buffer[6]=Channel0*Channel0_AmplitudeMultiple;
        Buffer[7]=Channel0*Channel1_AmplitudeMultiple;

        Channel0=Buffer[8];
        Buffer[8]=Channel0*Channel0_AmplitudeMultiple;
        Buffer[9]=Channel0*Channel1_AmplitudeMultiple;

        Channel0=Buffer[10];
        Buffer[10]=Channel0*Channel0_AmplitudeMultiple;
        Buffer[11]=Channel0*Channel1_AmplitudeMultiple;

        Channel0=Buffer[12];
        Buffer[12]=Channel0*Channel0_AmplitudeMultiple;
        Buffer[13]=Channel0*Channel1_AmplitudeMultiple;

        Channel0=Buffer[14];
        Buffer[14]=Channel0*Channel0_AmplitudeMultiple;
        Buffer[15]=Channel0*Channel1_AmplitudeMultiple;

        Buffer=&Buffer[16];
      }
      while(Length>0){
        Length--;

        Channel0=Buffer[0];
        Buffer[0]=Channel0*Channel0_AmplitudeMultiple;
        Buffer[1]=Channel0*Channel1_AmplitudeMultiple;

        Buffer=&Buffer[2];
      }

      break;
    case vH_AudioResample_Volume_ChannelMode_ChannelR:

      while(Length>=8){
        Length-=8;

        Channel1=Buffer[1];
        Buffer[0]=Channel1*Channel0_AmplitudeMultiple;
        Buffer[1]=Channel1*Channel1_AmplitudeMultiple;

        Channel1=Buffer[3];
        Buffer[2]=Channel1*Channel0_AmplitudeMultiple;
        Buffer[3]=Channel1*Channel1_AmplitudeMultiple;

        Channel1=Buffer[5];
        Buffer[4]=Channel1*Channel0_AmplitudeMultiple;
        Buffer[5]=Channel1*Channel1_AmplitudeMultiple;

        Channel1=Buffer[7];
        Buffer[6]=Channel1*Channel0_AmplitudeMultiple;
        Buffer[7]=Channel1*Channel1_AmplitudeMultiple;

        Channel1=Buffer[9];
        Buffer[8]=Channel1*Channel0_AmplitudeMultiple;
        Buffer[9]=Channel1*Channel1_AmplitudeMultiple;

        Channel1=Buffer[11];
        Buffer[10]=Channel1*Channel0_AmplitudeMultiple;
        Buffer[11]=Channel1*Channel1_AmplitudeMultiple;

        Channel1=Buffer[13];
        Buffer[12]=Channel1*Channel0_AmplitudeMultiple;
        Buffer[13]=Channel1*Channel1_AmplitudeMultiple;

        Channel1=Buffer[15];
        Buffer[14]=Channel1*Channel0_AmplitudeMultiple;
        Buffer[15]=Channel1*Channel1_AmplitudeMultiple;

        Buffer=&Buffer[16];
      }
      while(Length>0){
        Length--;

        Channel1=Buffer[1];
        Buffer[0]=Channel1*Channel0_AmplitudeMultiple;
        Buffer[1]=Channel1*Channel1_AmplitudeMultiple;

        Buffer=&Buffer[2];
      }

      break;
    case vH_AudioResample_Volume_ChannelMode_ChannelSwap:

      while(Length>=8){
        Length-=8;

        Channel0=Buffer[0];
        Channel1=Buffer[1];
        Buffer[0]=Channel1*Channel0_AmplitudeMultiple;
        Buffer[1]=Channel0*Channel1_AmplitudeMultiple;

        Channel0=Buffer[2];
        Channel1=Buffer[3];
        Buffer[2]=Channel1*Channel0_AmplitudeMultiple;
        Buffer[3]=Channel0*Channel1_AmplitudeMultiple;

        Channel0=Buffer[4];
        Channel1=Buffer[5];
        Buffer[4]=Channel1*Channel0_AmplitudeMultiple;
        Buffer[5]=Channel0*Channel1_AmplitudeMultiple;

        Channel0=Buffer[6];
        Channel1=Buffer[7];
        Buffer[6]=Channel1*Channel0_AmplitudeMultiple;
        Buffer[7]=Channel0*Channel1_AmplitudeMultiple;

        Channel0=Buffer[8];
        Channel1=Buffer[9];
        Buffer[8]=Channel1*Channel0_AmplitudeMultiple;
        Buffer[9]=Channel0*Channel1_AmplitudeMultiple;

        Channel0=Buffer[10];
        Channel1=Buffer[11];
        Buffer[10]=Channel1*Channel0_AmplitudeMultiple;
        Buffer[11]=Channel0*Channel1_AmplitudeMultiple;

        Channel0=Buffer[12];
        Channel1=Buffer[13];
        Buffer[12]=Channel1*Channel0_AmplitudeMultiple;
        Buffer[13]=Channel0*Channel1_AmplitudeMultiple;

        Channel0=Buffer[14];
        Channel1=Buffer[15];
        Buffer[14]=Channel1*Channel0_AmplitudeMultiple;
        Buffer[15]=Channel0*Channel1_AmplitudeMultiple;

        Buffer=&Buffer[16];
      }
      while(Length>0){
        Length--;

        Channel0=Buffer[0];
        Channel1=Buffer[1];
        Buffer[0]=Channel1*Channel0_AmplitudeMultiple;
        Buffer[1]=Channel0*Channel1_AmplitudeMultiple;

        Buffer=&Buffer[2];
      }

      break;
    default:

      while(Length>=8){
        Length-=8;

        Buffer[0]*=Channel0_AmplitudeMultiple;
        Buffer[1]*=Channel1_AmplitudeMultiple;
        
        Buffer[2]*=Channel0_AmplitudeMultiple;
        Buffer[3]*=Channel1_AmplitudeMultiple;
        
        Buffer[4]*=Channel0_AmplitudeMultiple;
        Buffer[5]*=Channel1_AmplitudeMultiple;
        
        Buffer[6]*=Channel0_AmplitudeMultiple;
        Buffer[7]*=Channel1_AmplitudeMultiple;
        
        Buffer[8]*=Channel0_AmplitudeMultiple;
        Buffer[9]*=Channel1_AmplitudeMultiple;
        
        Buffer[10]*=Channel0_AmplitudeMultiple;
        Buffer[11]*=Channel1_AmplitudeMultiple;

        Buffer[12]*=Channel0_AmplitudeMultiple;
        Buffer[13]*=Channel1_AmplitudeMultiple;

        Buffer[14]*=Channel0_AmplitudeMultiple;
        Buffer[15]*=Channel1_AmplitudeMultiple;

        Buffer=&Buffer[16];
      }
      while(Length>0){
        Length--;

        Buffer[0]=Buffer[0]*Channel0_AmplitudeMultiple;
        Buffer[1]=Buffer[1]*Channel1_AmplitudeMultiple;

        Buffer=&Buffer[2];
      }

      break;
  }

}



/**
 * 插值卷积函数
 * 
 * 
 * /  (a+2)|x|^3 - (a+3)|x|^2 + 1         |x|<1
 * |  a|x|^3 - 5a|x|^2 + 8a|x| - 4a     1<|x|<2
 * \  0                                 otherwise
 * 
 * a=-0.5时效果最好
 * 
 * /  1.5|x|^3 - 2.5|x|^2 + 1             |x|<1
 * |  -0.5|x|^3 + 2.5|x|^2 - 4|x| + 2   1<|x|<2
 * \  0                                 otherwise
 * 
*/

#define vH_AudioResample_CubicInterpolation_a  cH_AudioResample_FloatConst(-0.5)       //a的取值
#define vH_AudioResample_CubicInterpolation_A1 (vH_AudioResample_CubicInterpolation_a+cH_AudioResample_FloatConst(2.0))
#define vH_AudioResample_CubicInterpolation_B1 (-vH_AudioResample_CubicInterpolation_a-cH_AudioResample_FloatConst(3.0))
//#define vH_AudioResample_CubicInterpolation_C1 (cH_AudioResample_FloatConst(0.0))
#define vH_AudioResample_CubicInterpolation_D1 (cH_AudioResample_FloatConst(1.0))
#define vH_AudioResample_CubicInterpolation_A2 vH_AudioResample_CubicInterpolation_a
#define vH_AudioResample_CubicInterpolation_B2 (cH_AudioResample_FloatConst(-5.0)*vH_AudioResample_CubicInterpolation_a)
#define vH_AudioResample_CubicInterpolation_C2 (cH_AudioResample_FloatConst(8.0)*vH_AudioResample_CubicInterpolation_a)
#define vH_AudioResample_CubicInterpolation_D2 (cH_AudioResample_FloatConst(-4.0)*vH_AudioResample_CubicInterpolation_a)



//输出整型到Output缓存中 双声道 每通道的样本数据高16位与低16位交换 (F4的I2S是真坑 数据寄存器就16位) 若使用这个转换方法 H_AudioResample_IntegerType必须为32位
static void H_AudioResample_CubicInterpolation(H_AudioResample* ar,H_AudioResample_FloatType* Buffer,int Length){
  H_AudioResample_FloatType* Src_Fp;
  H_AudioResample_FloatType* LastData;
  int Src_Index;
  
  H_AudioResample_IntegerType Channel0;
  H_AudioResample_IntegerType Channel1;

  int I;
  int I_Block;
  int SizeOfPerOutput;

  Huint16* Dst_p;


  Length/=2;//将长度转换位采样数量
  
  I=ar->Output.I;
  I_Block=ar->Output.I_Block;
  SizeOfPerOutput=ar->Output.SizeOfPerOutput;

  LastData=ar->LastData;

  if(ar->ResampleCtrl.Status==vH_AudioResample_ResampleCtrl_Status_SpeedDefault){
    //无重采样
    
    Src_Fp=&LastData[4];
    for(Src_Index=0;Src_Index<2;Src_Index++){

      Channel0=(H_AudioResample_IntegerType)Src_Fp[0];
      Channel1=(H_AudioResample_IntegerType)Src_Fp[1];

      Src_Fp=&Src_Fp[2];

      //写入数据
      Dst_p=(Huint16*)&ar->Output.Buffer[I*SizeOfPerOutput+I_Block];

      Dst_p[0]=((Huint16*)&Channel0)[1];
      Dst_p[1]=((Huint16*)&Channel0)[0];
      Dst_p[2]=((Huint16*)&Channel1)[1];
      Dst_p[3]=((Huint16*)&Channel1)[0];

      if(I_Block==(SizeOfPerOutput-2)){
        int EmptyCount;
        int O;

        O=ar->Output.O;
        if(I<O){
          EmptyCount=O-I;
        }else{
          EmptyCount=ar->Output.OutputBufferBlockAllCount-I+O;
        }
        EmptyCount-=(ar->Output.OutputBufferBlockAllCount-ar->Output.OutputBufferBlockMaxCount);

        if(EmptyCount==0){

          goto Return;
        }

        if(I==(ar->Output.OutputBufferBlockAllCount-1)){
          I=0;
        }else{
          I++;
        }
        I_Block=0;
      }else{
        I_Block+=2;
      }
      //成功写入一个数据

    }
    
    Src_Fp=Buffer;
    for(;Src_Index<Length;Src_Index++){
      
      Channel0=(H_AudioResample_IntegerType)Src_Fp[0];
      Channel1=(H_AudioResample_IntegerType)Src_Fp[1];

      Src_Fp=&Src_Fp[2];

      //写入数据
      Dst_p=(Huint16*)&ar->Output.Buffer[I*SizeOfPerOutput+I_Block];

      Dst_p[0]=((Huint16*)&Channel0)[1];
      Dst_p[1]=((Huint16*)&Channel0)[0];
      Dst_p[2]=((Huint16*)&Channel1)[1];
      Dst_p[3]=((Huint16*)&Channel1)[0];

      if(I_Block==(SizeOfPerOutput-2)){
        int EmptyCount;
        int O;

        O=ar->Output.O;
        if(I<O){
          EmptyCount=O-I;
        }else{
          EmptyCount=ar->Output.OutputBufferBlockAllCount-I+O;
        }
        EmptyCount-=(ar->Output.OutputBufferBlockAllCount-ar->Output.OutputBufferBlockMaxCount);

        if(EmptyCount==0){

          goto Return;
        }

        if(I==(ar->Output.OutputBufferBlockAllCount-1)){
          I=0;
        }else{
          I++;
        }
        I_Block=0;
      }else{
        I_Block+=2;
      }
      //成功写入一个数据
      
    }
  }else{
    //重采样

    
    H_AudioResample_FloatType Src_Index_F;

    H_AudioResample_FloatType Channel0_F;
    H_AudioResample_FloatType Channel1_F;

    H_AudioResample_FloatType Cubic_W0; //x0对应的卷积权重
    H_AudioResample_FloatType Cubic_W1; //x1对应的卷积权重
    H_AudioResample_FloatType Cubic_W2; //x2对应的卷积权重
    H_AudioResample_FloatType Cubic_W3; //x3对应的卷积权重
    
    int DstLength;
    int Dst_Index;

    if(ar->ResampleCtrl.Status==vH_AudioResample_ResampleCtrl_Status_SpeedDown){
      DstLength=Length-Length*ar->ResampleCtrl.SRC_Ratio;
      if(DstLength==Length){
        DstLength-=1;
      }
    }else{
      DstLength=Length+Length*ar->ResampleCtrl.SRC_Ratio;
      if(DstLength==Length){
        DstLength+=1;
      }
    }

    for(Dst_Index=0;Dst_Index<DstLength;Dst_Index++){
      H_AudioResample_FloatType temp_F;

      Src_Index_F=(H_AudioResample_FloatType)(Dst_Index*Length)/(H_AudioResample_FloatType)DstLength;
      Src_Index=Src_Index_F;
      //4个采样数据位x0 x1 x2 x3
      //此时Src_Index已指向 x3

      temp_F=Src_Index_F-(H_AudioResample_FloatType)(Src_Index-1);
      Cubic_W0=temp_F*temp_F*temp_F*vH_AudioResample_CubicInterpolation_A2
      +temp_F*temp_F*vH_AudioResample_CubicInterpolation_B2
      +temp_F*vH_AudioResample_CubicInterpolation_C2
      +vH_AudioResample_CubicInterpolation_D2;

      temp_F=Src_Index_F-(H_AudioResample_FloatType)Src_Index;
      Cubic_W1=temp_F*temp_F*temp_F*vH_AudioResample_CubicInterpolation_A1
      +temp_F*temp_F*vH_AudioResample_CubicInterpolation_B1
      //+temp_F*vH_AudioResample_CubicInterpolation_C1
      +vH_AudioResample_CubicInterpolation_D1;

      temp_F=(H_AudioResample_FloatType)(Src_Index+1)-Src_Index_F;
      Cubic_W2=temp_F*temp_F*temp_F*vH_AudioResample_CubicInterpolation_A1
      +temp_F*temp_F*vH_AudioResample_CubicInterpolation_B1
      //+temp_F*vH_AudioResample_CubicInterpolation_C1
      +vH_AudioResample_CubicInterpolation_D1;

      temp_F=(H_AudioResample_FloatType)(Src_Index+2)-Src_Index_F;
      Cubic_W3=temp_F*temp_F*temp_F*vH_AudioResample_CubicInterpolation_A2
      +temp_F*temp_F*vH_AudioResample_CubicInterpolation_B2
      +temp_F*vH_AudioResample_CubicInterpolation_C2
      +vH_AudioResample_CubicInterpolation_D2;

      Channel0_F=cH_AudioResample_FloatConst(0.0);
      Channel1_F=cH_AudioResample_FloatConst(0.0);
      Src_Fp=Buffer;
      switch(Src_Index){

        case 0:

          Channel0_F+=Cubic_W0*LastData[2];
          Channel1_F+=Cubic_W0*LastData[3];
          Channel0_F+=Cubic_W1*LastData[4];
          Channel1_F+=Cubic_W1*LastData[5];
          Channel0_F+=Cubic_W2*LastData[6];
          Channel1_F+=Cubic_W2*LastData[7];
          Channel0_F+=Cubic_W3*Src_Fp[0];
          Channel1_F+=Cubic_W3*Src_Fp[1];

          break;

        case 1:

          Channel0_F+=Cubic_W0*LastData[4];
          Channel1_F+=Cubic_W0*LastData[5];
          Channel0_F+=Cubic_W1*LastData[6];
          Channel1_F+=Cubic_W1*LastData[7];
          Channel0_F+=Cubic_W2*Src_Fp[0];
          Channel1_F+=Cubic_W2*Src_Fp[1];
          Channel0_F+=Cubic_W3*Src_Fp[2];
          Channel1_F+=Cubic_W3*Src_Fp[3];

          break;
        
        case 2:

          Channel0_F+=Cubic_W0*LastData[6];
          Channel1_F+=Cubic_W0*LastData[7];
          Channel0_F+=Cubic_W1*Src_Fp[0];
          Channel1_F+=Cubic_W1*Src_Fp[1];
          Channel0_F+=Cubic_W2*Src_Fp[2];
          Channel1_F+=Cubic_W2*Src_Fp[3];
          Channel0_F+=Cubic_W3*Src_Fp[4];
          Channel1_F+=Cubic_W3*Src_Fp[5];

          break;
        
        default:

          Src_Fp=&Src_Fp[Src_Index*2-6];
          Channel0_F+=Cubic_W0*Src_Fp[0];
          Channel1_F+=Cubic_W0*Src_Fp[1];
          Channel0_F+=Cubic_W1*Src_Fp[2];
          Channel1_F+=Cubic_W1*Src_Fp[3];
          Channel0_F+=Cubic_W2*Src_Fp[4];
          Channel1_F+=Cubic_W2*Src_Fp[5];
          Channel0_F+=Cubic_W3*Src_Fp[6];
          Channel1_F+=Cubic_W3*Src_Fp[7];

          break;
      }

      Channel0=(H_AudioResample_IntegerType)Channel0_F;
      Channel1=(H_AudioResample_IntegerType)Channel1_F;

      //写入数据
      Dst_p=(Huint16*)&ar->Output.Buffer[I*SizeOfPerOutput+I_Block];

      Dst_p[0]=((Huint16*)&Channel0)[1];
      Dst_p[1]=((Huint16*)&Channel0)[0];
      Dst_p[2]=((Huint16*)&Channel1)[1];
      Dst_p[3]=((Huint16*)&Channel1)[0];

      if(I_Block==(SizeOfPerOutput-2)){
        int EmptyCount;
        int O;

        O=ar->Output.O;
        if(I<O){
          EmptyCount=O-I;
        }else{
          EmptyCount=ar->Output.OutputBufferBlockAllCount-I+O;
        }
        EmptyCount-=(ar->Output.OutputBufferBlockAllCount-ar->Output.OutputBufferBlockMaxCount);

        if(EmptyCount==0){

          goto Return;
        }

        if(I==(ar->Output.OutputBufferBlockAllCount-1)){
          I=0;
        }else{
          I++;
        }
        I_Block=0;
      }else{
        I_Block+=2;
      }

    }
    
  }

Return:
  Src_Fp=&Buffer[Length*2-8];
  LastData[0]=Src_Fp[0];
  LastData[1]=Src_Fp[1];
  LastData[2]=Src_Fp[2];
  LastData[3]=Src_Fp[3];
  LastData[4]=Src_Fp[4];
  LastData[5]=Src_Fp[5];
  LastData[6]=Src_Fp[6];
  LastData[7]=Src_Fp[7];

  ar->Output.I_Block=I_Block;
  ar->Output.I=I;
}


